package com.haodf.skeleton

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import com.haodf.skeleton.anim.BaiJvGuoXiLoadingAnimtor
import com.haodf.skeleton.anim.ILoadingAnimtor
import com.haodf.skeleton.anim.RuoYinRuoXianLoadingAnimtor

/**
 * @author xiaxiao
 * @date 2023/4/26.
 * 骨架屏
 *
 * listview item style:
 * .. 矩阵代表图片
 * || 代表字符串
 * style 1:
 * ...........
 * ........... |||||||      ||||||||||||||||||||||||
 * ...........
 * ........... |||||||||||||||||||||||||||||||||||||
 *
 * style 2:
 * ...........
 * ...........
 * ...........
 * ...........
 * |||||||||||
 * |||||||||||
 *
 * style 3:
 * |||||||||||||||||                           |||
 * |||||||||||||||||||||||||||||||||||||
 * |||||||||||||||||||||||||||||||||||||
 * |||||||||||||||||||||||||||||||||||||
 *                                 ||||||   ||||||
 *
 * style 4:
 * |||||  ||||||||||||||||||||||||||||||||    |||
 *
 */
class SkeletonLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    companion object {
        var DEBUG = false

        private const val STATUS_LOADING = 0
        private const val STATUS_NORMAL = 1

        private const val PLACE_HOLDER_TEXT = "HdFzX好大夫在线"
    }

    private var skeletonView: SkeletonView? = null
    private var mPageStatus = STATUS_NORMAL
    private var dismissAnim: ValueAnimator? = null
    private var config: Config = Config()

    private val obj = Any()

    init {
        skeletonView = SkeletonView(context)
        skeletonView?.isClickable = true
        skeletonView?.isFocusable = true
    }

    private val childList: MutableList<TextView> = mutableListOf<TextView>()

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        if (config.toolsTextEnable && skeletonView?.isGrayLandReady() == false) {
            findAllTextView(getChildAt(0), childList)
            synchronized(obj) {
                childList.forEach {
                    if (it.text == null || it.text == "") {
                        it.text = PLACE_HOLDER_TEXT
                    }
                }
            }
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

    }


    private fun findAllTextView(view: View?, childList: MutableList<TextView>) {
        view ?: return
        if (view is TextView
            && view.visibility == View.VISIBLE
            && view.text.toString().isEmpty()
        ) {
            childList.add(view)
        } else if (view is ViewGroup) {
            val count = view.childCount
            for (i in 0 until count) {
                findAllTextView(view.getChildAt(i), childList)
            }
        }
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (mPageStatus == STATUS_LOADING) {
            skeletonView?.target = getChildAt(0)
            if (config.skeletonEnable && childCount == 1) {
                addView(skeletonView, 1)
                skeletonView?.layoutParams = LayoutParams(
                    this.measuredWidth,
                    this.measuredHeight
                )
            }
        } else {
            skeletonView?.visibility = View.GONE
        }
    }

    fun clearTexts() {
        synchronized(obj) {
            childList.forEach {
                if (it.text == PLACE_HOLDER_TEXT) {
                    it.text = ""
                }
            }
        }
        childList.clear()
        invalidate()
    }


    fun loading() {
        if (dismissAnim?.isRunning == true) {
            dismissAnim?.cancel()
        }
        mPageStatus = STATUS_LOADING
        skeletonView?.alpha = 1.0f
        skeletonView?.visibility = View.VISIBLE
    }

    fun normal() {
        if (config.toolsTextEnable) {
            clearTexts()
        }
        if (dismissAnim == null) {
            createAnim()
        }
        if (dismissAnim?.isRunning == true) {
            dismissAnim?.cancel()
        }
        dismissAnim?.start()
    }

    /**
     * 这个行不通
     * */
    fun wrapView(target: View) {
        val parent = target.parent
        if (parent !is ViewGroup) return
        if (parent is SkeletonLayout) return
        val clazz = parent.javaClass
        val targetParent = clazz.getConstructor(Context::class.java).newInstance(this.context)
        val index = parent.indexOfChild(target)
        val layoutParams = target.layoutParams
        parent.removeView(target)

        val insertParent = this
        insertParent.addView(
            targetParent,
            0,
            LayoutParams(
                LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT
            )
        )
        targetParent.addView(target, layoutParams)
        parent.addView(insertParent, index, layoutParams)
    }

    fun config(options: Config.() -> Unit) {
        config.options()
        config.listviewItemType?.let { skeletonView?.listviewItemType = it }
        config.loadingAnim?.let {
            val a: ILoadingAnimtor? = when (it) {
                ILoadingAnimtor.TYPE_BAI_JV_GUO_XI -> {
                    BaiJvGuoXiLoadingAnimtor(skeletonView ?: return@let)
                }
                ILoadingAnimtor.TYPE_RUO_YIN_RUO_XIAN -> {
                    val r = RuoYinRuoXianLoadingAnimtor(skeletonView ?: return@let)
                    r.setPaint(skeletonView?.getAPaint() ?: return@let)
                    r
                }
                else -> {
                    null
                }
            }
            a?.let { aa ->
                skeletonView?.setLoadingAnim(aa)
            }
        }
        config.customLoadingAnim?.let { skeletonView?.setLoadingAnim(it) }

        DEBUG = config.debug
        requestLayout()
    }

    private fun createAnim() {
        dismissAnim = ValueAnimator.ofInt(1, 100)
        dismissAnim?.interpolator = null
        dismissAnim?.addUpdateListener {
            skeletonView?.alpha = 1 - it.animatedFraction
            if (it.animatedValue == 100) {
                skeletonView?.visibility = View.GONE
                skeletonView?.alpha = 1f
                mPageStatus = STATUS_NORMAL
            }
        }
        dismissAnim?.duration = 200
    }


    inner class Config {
        var listviewItemType: ItemParams? = null
        var skeletonEnable: Boolean = true
        var customLoadingAnim: ILoadingAnimtor? = null
        var loadingAnim: Int? = null
        var toolsTextEnable: Boolean = false //优化 tools 属性
        var debug: Boolean = false //打印日志
    }
}